#include "../include/head.h"

// 服务端当前目录
//char serverDir[256] = "~";
char *serverDir;
int exitPipe[2];

void handler(int signum){
    printf("signum = %d\n", signum);
    write(exitPipe[1],"1",1);
}



int main()
{
    serverDir = (char *)calloc(1024, sizeof(char));
    strcpy(serverDir,"../UserDir");
    pipe(exitPipe);// 这个pipe要fork之前
    if(fork())
    {
        //只有父进程
        close(exitPipe[0]);
        signal(SIGUSR1,handler);
        int pid = getpid();
        printf("父进程pid = %d\n", pid);
        wait(NULL);
        printf("Parent is going to exit!\n");
        exit(0);
    }

    close(exitPipe[1]);
    //初始化三个队列
    //初始化三个共享资源结构体
    shareRes_t arges[3];



    //初始化pthread_Data
    pthread_data_t pthread_data;
    init_pthread_data(&pthread_data,3);

    taskQueue_t queues[2];
    for(int i =0;i<2;i++)
    {
        init_queue(&queues[i]);
    }

    //初始化clientinfo
    int clientInfo[1024];
    for(int i = 0;i<1024;i++)
    {
        clientInfo[i]=-1;
    }
    //初始化clientinfo锁
    pthread_mutex_t mutex_client_info = PTHREAD_MUTEX_INITIALIZER;

    //初始化标志位
    int exitFlag = 0;


    int clientID = 1;
    int maxIndex = 0;

    int sockfd = initTcp("127.0.0.1","43210");
    int epfd = epoll_create(1);
    epollAdd(epfd,sockfd,0);//0水平触发，1边缘触发
    epollAdd(epfd,exitPipe[0],1);

    //创建线程池
    pthread_mutex_t long_queue_mutex;
    pthread_cond_t long_queue_cond;
    pthread_mutex_init(&long_queue_mutex, NULL);
    pthread_cond_init(&long_queue_cond,NULL);

    pthread_mutex_t short_queue_mutex;
    pthread_cond_t short_queue_cond;
    pthread_mutex_init(&short_queue_mutex, NULL);
    pthread_cond_init(&short_queue_cond,NULL);
    makeworker(arges,&epfd,&pthread_data,clientInfo,&exitFlag,&mutex_client_info,queues,&long_queue_mutex,&short_queue_mutex,&long_queue_cond,&short_queue_cond);

    struct epoll_event readySet[1024];

    while(1)
    {
        int readyNum = epoll_wait(epfd,readySet,1024,-1);
        // printf("1\n");
        for(int i = 0; i<readyNum; ++i)
        {
            if(readySet[i].data.fd == sockfd)
            {
                int netfd = accept(sockfd,NULL,NULL);
                // printf("accept:%d\n",netfd);
                maxIndex = netfd > maxIndex ? netfd : maxIndex;
                pthread_mutex_lock(&mutex_client_info);
                clientInfo[netfd] = clientID;
                pthread_mutex_unlock(&mutex_client_info);
                clientID++;
                epollAdd(epfd,netfd,0);
            }
            else if(readySet[i].data.fd == exitPipe[0])
            {
                pthread_mutex_lock(&mutex_client_info);
                exitFlag =1;
               
                pthread_cond_broadcast(&long_queue_cond);
                pthread_cond_broadcast(&short_queue_cond);
                
                pthread_mutex_unlock(&mutex_client_info);
                for(int i = 0; i<pthread_data.workernum;i++)
                {
                    pthread_join(pthread_data.ptidarr[i],NULL);
                }
                exit(0);
            }
            else
            {

                for(int j =4;j<=maxIndex;++j)
                {
                    if(readySet[i].data.fd == j)
                    {
                        MSG_TYPE type;
                       
                        int recvret;
                        // printf("============================%d\n",j);
                        //recv(j, &type, sizeof(type), MSG_WAITALL);
                        //printf("before recvret\n");
                        recvret = recvn(j,&type,sizeof(type),NULL);
                        // printf("is here %d \n",type);
                        //printf("after recvret ,type = %d\n",type);
                        if(!ErrCheck_ClientClose(recvret,j,epfd,&mutex_client_info,clientInfo)){continue;}
                        //printf("client %d:task\n", type);
                        if(type == C_LINK_START)
                        {
                            //printf("daad\n");
                            continue;
                        }
                        else if(type == C_LINK_CLOSE)
                        {
                            close(j);
                            epollDel(epfd,j);

                            pthread_mutex_lock(&mutex_client_info);
                            clientInfo[j] = -1;
                            pthread_mutex_unlock(&mutex_client_info);
                        }
                        else 
                        {
                            //RequestPackage* requestPackage = (RequestPackage*)calloc(1,sizeof(RequestPackage));
                            taskNode_t* task = (taskNode_t*)calloc(1,sizeof(taskNode_t));

                            task->epfd = &epfd;
                            task->netfd = j;
                            pthread_mutex_lock(&mutex_client_info);
                            task->client_id = clientInfo[j];
                            pthread_mutex_unlock(&mutex_client_info);

                           
                            task->type = type;

                            int recvlen;
                            //recv(j,&recvlen,sizeof(recvlen),MSG_WAITALL);
                            recvret = recvn(j,&recvlen,sizeof(recvlen),NULL);
                            if(!ErrCheck_ClientClose(recvret,j,epfd,&mutex_client_info,clientInfo)){continue;}
                            //printf("1 = %d\n", recvlen);
                            //recv(j,task->virtualPath,recvlen,MSG_WAITALL);
                            recvret = recvn(j,task->virtualPath,recvlen,NULL);
                            if(!ErrCheck_ClientClose(recvret,j,epfd,&mutex_client_info,clientInfo)){continue;}
                            //printf("2 = %d\n", recvlen);
                            //recv(j,&recvlen,sizeof(recvlen),MSG_WAITALL);
                            recvret = recvn(j,&recvlen,sizeof(recvlen),NULL);
                            if(!ErrCheck_ClientClose(recvret,j,epfd,&mutex_client_info,clientInfo)){continue;}
                            //printf("3 = %d\n", recvlen);
                            if(recvlen!=0)
                            {    
                                //recv(j,task->args,recvlen,MSG_WAITALL);
                                recvn(j,task->args,recvlen,NULL);
                                if(!ErrCheck_ClientClose(recvret,j,epfd,&mutex_client_info,clientInfo)){continue;}
                            }
                            

                            //printf("4 = %d\n", recvlen);
                            task->pNext = NULL;

                            if(type == C_OP_PUTS_BEGIN)
                            {
                                // printf("puts\n");
                                //printf("before main thread insert %p size :%p -  %d\n",&arges[0].taskqueue,&arges[0].taskqueue.queuesize,arges[0].taskqueue.queuesize);
                                pthread_mutex_lock(arges[1].mutex_taskqueue);
                                tail_insert(&arges[1].taskqueue,task);
                               // printf("after main thread insert %p size : %p -  %d\n",&arges[0].taskqueue,&arges[0].taskqueue.queuesize,arges[0].taskqueue.queuesize);
                                pthread_cond_broadcast(arges[1].cond);
                                pthread_mutex_unlock(arges[1].mutex_taskqueue);
                            }
                            else if(type == C_OP_GETS_BEGIN)
                            {
                                // printf("gets\n");
                                //printf("before main thread insert %p size : %p -  %d\n",&arges[1].taskqueue,&arges[1].taskqueue.queuesize,arges[1].taskqueue.queuesize);
                                pthread_mutex_lock(arges[1].mutex_taskqueue);
                                // printf("开始插入结点\n");
                                tail_insert(&arges[1].taskqueue, task);
                                //printf("after main thread insert %p size : %p -  %d\n",&arges[1].taskqueue,&arges[1].taskqueue.queuesize,arges[1].taskqueue.queuesize);
                                pthread_cond_broadcast(arges[1].cond);
                                pthread_mutex_unlock(arges[1].mutex_taskqueue);
                            }
                            else
                            {  
                                // printf("short-\n");
                                pthread_mutex_lock(arges[0].mutex_taskqueue);
                                //printf("开始塞入队列\n");
                                //printf("before main thread insert %p size : %p -  %d\n",&arges[2].taskqueue,&arges[2].taskqueue.queuesize,arges[2].taskqueue.queuesize);
                                tail_insert(&arges[0].taskqueue, task);
                                //printf("after main thread insert %p size : %p -  %d\n",&arges[2].taskqueue,&arges[2].taskqueue.queuesize,arges[2].taskqueue.queuesize);
                                pthread_cond_broadcast(arges[0].cond);
                                pthread_mutex_unlock(arges[0].mutex_taskqueue);
                            }

                        }
                    }
                }
            }
        }
    }
}
